using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Web.UI;

public partial class C : Page
{
    protected void Page_Init(object sender,EventArgs e)
    {
        //this.Title = this.Title+"xxxxyyyykkk";
    }
    protected void Page_Load( object sender,EventArgs e )
    {

    }

    // Handler
    public static string Handler( NameValueCollection nvc )
    {
        string code = nvc["code"];
        if( string.IsNullOrEmpty(code) ){
            return "";
        }

        XmlDocument doc = new XmlDocument();
        doc.LoadXml( code );
        XmlNodeList list = doc.SelectNodes( "/code/class" );

        StringBuilder sb = new StringBuilder();
        // 生成类
        foreach( XmlNode node in list )
            sb.Append( GenClass.ClassTemplate( new ClassInfo( node ) ) );
        // 生成Sql
        foreach( XmlNode node in list )
            sb.Append( GenSql.SqlTemplate( new TableInfo( node ) ) );
        // 生成Html
        foreach( XmlNode node in list )
            sb.Append( GenHtml.HtmlTemplate( new FormInfo( node) ) );        

        return sb.ToString();
    }
}

public class ClassInfo
{
    public string Name = "";
    public IList<PropertyInfo> Properties = new List<PropertyInfo>();

    public ClassInfo( XmlNode node )
    {
        Name = node.Attributes["name"].Value+"Info";
        XmlNodeList list = node.SelectNodes( "property" );
        for( int i=0,len=list.Count;i<len;i++ )
            Properties.Add( new PropertyInfo( this,list[i] ) );
    }
}
public class PropertyInfo
{
    public string Modifier = "";
    public string Type = "";     // 属性类型
    public string Name = "";     // 属性签名
    public string Value = "";    // 属性默认值

    public string Comment = "";    // 评论  
    public string DbColumn = "";   // 数据库表列名
    public string WebColumn = "";  // Web表单列名
    
    public ClassInfo Class = null;

    // 构造器
    public PropertyInfo( ClassInfo classInfo,XmlNode node )
    {
        this.Class = classInfo;
        
        // 必选
        this.Type     = node.Attributes["type"].Value;
        this.Name     = node.Attributes["name"].Value;
        this.Value    = node.Attributes["value"].Value;
        
        this.DbColumn = this.WebColumn = this.Name;
        
        // 可选
        if( null!=node.Attributes["comment"] )
            this.Comment = node.Attributes["comment"].Value;
        if( null!=node.Attributes["modifier"] )
            this.Modifier = node.Attributes["modifier"].Value;
        if( null!=node.Attributes["dbColumn"] )
            this.DbColumn = node.Attributes["dbColumn"].Value;
        if( null!=node.Attributes["webColumn"] )
            this.WebColumn= node.Attributes["webColumn"].Value;
    }
}

public class GenClass
{
    private static string WRAPPER = "    public class {0} : IEnumerable,IEntity\r\n    {{\r\n{1}\r\n    }}\r\n\r\n\r\n";

    public static string ClassTemplate( ClassInfo info )
    {
        IList<PropertyInfo> items = info.Properties;
        StringBuilder sb = new StringBuilder();

        sb.Append( "      #region 构造器\r\n" );
        sb.Append( Constructors( info ) );
        sb.Append( "      #endregion 构造器\r\n\r\n" );
        
        sb.Append( "      #region Public Properties\r\n" );
        sb.Append( GenProperties.Properties( items ) );
        sb.Append( "      #endregion Public Properties\r\n\r\n" );

        sb.Append( "      #region IEnumerable 接口\r\n" );
        sb.Append( GenProperties.IEnumerableMethod( items ) );
        sb.Append( "      #endregion IEnumerable 接口\r\n\r\n" );

        sb.Append( "      #region ToString Method\r\n" );
        sb.Append( GenProperties.ToStringMethod() );
        sb.Append( GenProperties.ToJsonMethod( items ) + "\r\n" );
        sb.Append( GenProperties.ToXmlMethod( items ) + "\r\n" );
        sb.Append( GenProperties.ToHtmlMethod( items ) + "\r\n" );
        sb.Append( GenProperties.ToTextMethod( items ) + "\r\n" );
        sb.Append( "      #endregion ToString Method\r\n\r\n" );

        sb.Append( "      #region Private Member\r\n" );
        sb.Append( GenProperties.Members( items )  );
        sb.Append( "      #endregion Private Member" );
/**
        sb.Append( "      ==============以下代码不属于DataModel类===================\r\n" );
        sb.Append( GenProperties.ParseTo( items )  );
*/
        return string.Format( WRAPPER,info.Name,sb.ToString() );
    }
    
    // 生成构造器
    public static string Constructors( ClassInfo info  )
    {
        StringBuilder sb = new StringBuilder();
        sb.Append( string.Format(
@"        //1
        public {0}(){{}}
        //2
        public {0}( NameValueCollection nvc )
        {{
{1}
        }}
        //3
        public {0}( DataRow row )
        {{
            DataColumnCollection dcc = row.Table.Columns;

{2}
        }}
",info.Name,WebMapping(info.Properties),DbMapping(info.Properties) ));
        
        return sb.ToString();
    }
    
    private static string WebMapping( IList<PropertyInfo> items )
    {
        string[] ss = new string[items.Count];
        for( int i=0,len=items.Count;i<len;i++ )
        {
            if( items[i].Type.ToLower() != "string" ){
                ss[i] = ( string.Format(
@"            if( !string.IsNullOrEmpty(nvc[""{2}""]) ){{ {0} r; {0}.TryParse( nvc[""{2}""],out r ); this.{1} = r;  }}",
                    items[i].Type,items[i].Name,items[i].WebColumn  ));
            }else{
                ss[i] = ( string.Format(
@"            if( !string.IsNullOrEmpty(nvc[""{1}""]) ){{ this.{0} = nvc[""{1}""];  }}",
                    items[i].Name,items[i].WebColumn  ));
            }
        }
        return string.Join( "\r\n",ss );
    }
    private static string DbMapping( IList<PropertyInfo> items )
    {
        string[] ss = new string[items.Count];
        for( int i=0,len=items.Count;i<len;i++ ){
            ss[i] = ( string.Format(
@"            if( dcc.Contains(""{2}"") && DBNull.Value!=row[""{2}""] ){{ this.{1} = ({0})row[""{2}""];  }}",
                    items[i].Type,items[i].Name,items[i].DbColumn ));
        }
        return string.Join( "\r\n",ss );
    }
}
public class GenProperties
{

    private static string PRIVATE_MEMBER =
"        private {0} _{1} = {2};\r\n";
    private static string PUBLIC_PROPERTY =
@"        public virtual {0} {1}
        {{
            get{{ return _{1};  }}
            set{{ _{1} = value; }}
        }}
";
    private static string PUBLIC_METHOD_GetEnumerator_WARP =
@"        public IEnumerator GetEnumerator()
        {{
{0}
        }}
";
    private static string PUBLIC_METHOD_GetEnumerator_ITEM =
"            yield return this.{0};";

    // 生成私有成员
    public static string Members( IList<PropertyInfo> items )
    {
        StringBuilder sb = new StringBuilder();
        for( int i=0,len=items.Count;i<len;i++ ){
            sb.Append( string.Format( PRIVATE_MEMBER,
                                        items[i].Type,
                                        items[i].Name,
                                        items[i].Value
                                     ));
        }
        return sb.ToString();
    }
    
    // 生成属性
    public static string Properties( IList<PropertyInfo> items )
    {
        StringBuilder sb = new StringBuilder();
        for( int i=0,len=items.Count;i<len;i++ )
        {
            sb.Append( string.Format( PUBLIC_PROPERTY,
                                      items[i].Type,
                                      items[i].Name
                                     ));
        }
        return sb.ToString();
    }

    // 生成IEnumerable接口方法
    public static string IEnumerableMethod( IList<PropertyInfo> items )
    {
        string[] ss = new string[items.Count];
        for( int i=0,len=items.Count;i<len;i++ ){
            ss[i] = ( string.Format( PUBLIC_METHOD_GetEnumerator_ITEM,items[i].Name ) );
        }
        string s = string.Format( PUBLIC_METHOD_GetEnumerator_WARP,string.Join("\r\n",ss) );
        return s;
    }

    // 生成ToString方法
    public static string ToStringMethod()
    {
      return
@"        public override string ToString()
        {
            return ToText();
        }
        public virtual string ToString( string format)
        {
            format = format.ToLower();
            switch( format )
            {
                case ""json"" :
                    return ToJson();
                case ""xml"" :
                    return ToXml();
                case ""html"" :
                    return ToHtml();
                default :
                    return ToText();
            }
        }
";
    }
    
    public static string ToJsonMethod( IList<PropertyInfo> items )
    {
        string s =
@"        protected virtual string ToJson()
        {{
            string s = string.Format
(
@""{{{{{0}}}}}"",
{1}
);
        return s;
        }}";

        int len = items.Count;
        string[] ss0 = new string[len];
        for( int i=0;i<len;i++ ){
            ss0[i] = string.Format( @"'{0}':'{{{1}}}'",items[i].WebColumn,i );
        }
        string[] ss1 = new string[len];
        for( int i=0;i<len;i++ ){
            ss1[i] = string.Concat( "My.Convert.JsonEncode(",items[i].Name,".ToString())" );
        }
        
        return string.Format( s,string.Join(",\r\n",ss0),string.Join(",\r\n",ss1) );
    }
    
    public static string ToXmlMethod( IList<PropertyInfo> items )
    {
        string s =
@"        protected virtual string ToXml()
        {
            throw new Exception( ""不支持"" );
        }";
        return s;
    }
    
    public static string ToHtmlMethod( IList<PropertyInfo> items )
    {
        string s =
@"        protected virtual string ToHtml()
        {
            throw new Exception( ""不支持"" );
        }";
        return s;
    }
    
    public static string ToTextMethod( IList<PropertyInfo> items )
    {
        string s =
@"        protected virtual string ToText()
        {
            List<string> list = new List<string>();
            foreach( object o in this ){
                list.Add( o.ToString() );
            }
            return string.Join( ""\r\n"",list.ToArray() );
        }";
        return s;
    }

/**
    // 生成数据表转换代码,此方法不属于DataModel
    public static string ParseTo( IList<PropertyInfo> items )
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(
@"        public XxxInfo ParseToXxxInfo( DataRow row )
        {
            if( null==row ){ throw new ArgumentNullException( ""参数不能为null"" );  }

            XxxInfo info = new XxxInfo();
            DataColumnCollection dcc = row.Table.Columns;

");
        for( int i=0,len=items.Count;i<len;i++ ){
             sb.Append( string.Format(
             "            if( dcc.Contains(_{0}) && DBNull.Value!=row[_{0}] ){{ info.{0} = ({1})row[_{0}];  }}\r\n",
                          items[i].Name,
                          items[i].Type
                          ));
        }
        sb.Append(
@"
            return info;
        }
");

        sb.Append( "\r\n" );

        sb.Append( "      #region Private Member\r\n" );
        for( int i=0,len=items.Count;i<len;i++ ){
            sb.Append( string.Format(
            "        private string _{0} = \"\";\r\n",
                     items[i].Name
            ));
        }
        sb.Append( "      #endregion Private Member\r\n" );
        return sb.ToString();
    }
*/
}

#region Data
public class TableInfo
{
    public string Name = "";
    public IList<ColumnInfo> Columns = new List<ColumnInfo>();
    
    public TableInfo( XmlNode node )
    {
        Name = node.Attributes["names"].Value;
        XmlNodeList list = node.SelectNodes( "property" );
        foreach( XmlNode info in list )
            Columns.Add( new ColumnInfo( this,info ) );
    }
}
public class ColumnInfo
{
    public string Name = "";       // 签名
    public string Type = "";       // 类型
    public string Length = "";     // 类型长度
    public string Constraint = ""; // 约束
    public string Default = "";    // 默认值

    public TableInfo Table = null;
    
    // 构造器
    public ColumnInfo( TableInfo table,XmlNode node )
    {
        this.Table = table;
        this.Name = node.Attributes["name"].Value;
        
        node = node.SelectSingleNode("sqlserver");
        if( null==node )
            return;
        
        // 必选
        this.Type = node.Attributes["type"].Value;
        
        // 可选
        if( null!=node.Attributes["length"] )
            this.Length = node.Attributes["length"].Value;
        if( null!=node.Attributes["constraint"] )
            this.Constraint = node.Attributes["constraint"].Value;
        if( null!=node.Attributes["default"] )
            this.Default = "Default " + node.Attributes["default"].Value;
    }
}
public class GenSql
{
    public static string SqlTemplate( TableInfo info )
    {
        StringBuilder sb = new StringBuilder();
        sb.Append( GenCreateTableSql( info.Columns ) );
        sb.Append( GenDropTableSql( info.Columns ) );
        sb.Append( GenSelectSql( info.Columns ) );
        sb.Append( GenInsertSql( info.Columns ) );
        sb.Append( GenUpdateSql( info.Columns ) );
        sb.Append( GenDeleteSql( info.Columns ) );
        sb.Append( GetSqlParameters( info.Columns ) );
        return sb.ToString();
    }
    
    
    private static string _CreateTableSql = "Create Table Prefix_{0}(\r\n{1}\r\n);\r\n";
    private static string _DropTableSql = "Drop Table Prefix_{0};\r\n";
    private static string _SelectSql = "Select {1} From Prefix_{0} Where Id=@Id;\r\n";
    private static string _InsertSql = "Insert Into Prefix_{0}({1}) Values ({2});\r\n";
    private static string _UpdateSql = "Update Prefix_{0} Set {1} Where Id=@Id;\r\n";
    private static string _DeleteSql = "Delete From Prefix_{0} Where Id in(@Ids);\r\n\r\n\r\n";
    
    private static string _Parm_Name = "protected const string {0} = \"{1}\";";
    private static string _SqlParameters = "SqlParameter[] parms = new SqlParameter[]{{\r\n{0}\r\n}};\r\n";
    
    private static string GenCreateTableSql( IList<ColumnInfo> infos )
    {
        string[] ss = new string[infos.Count];
        int i=0;
        foreach( ColumnInfo info in infos )
        {
            string type = " "+info.Type;
            string constraint = info.Constraint;
            string defalt = info.Default;
            
            if( !string.IsNullOrEmpty(info.Length) )
                type=string.Concat( type,"(",info.Length,")" );
            if( !string.IsNullOrEmpty(info.Constraint) )
                constraint=" "+info.Constraint;
            if( !string.IsNullOrEmpty(info.Default) )
                defalt=" "+info.Default;
            
            ss[i] = string.Concat( "    ",info.Name,type,constraint,defalt ); 
            ++i;
        }

        return string.Format( _CreateTableSql,infos[0].Table.Name,string.Join( ",\r\n",ss ) );
    }
    private static string GenDropTableSql( IList<ColumnInfo> infos )
    {
        return string.Format( _DropTableSql,infos[0].Table.Name );
    }
    
    private static string GenSelectSql( IList<ColumnInfo> infos )
    {
        string[] ss = new string[infos.Count];
        int i = 0;
        foreach( ColumnInfo info in infos ){
            ss[i] = info.Name; 
            ++i;         
        }
        
        return string.Format( _SelectSql, infos[0].Table.Name, string.Join( ",",ss) );
    }
    
    private static string GenInsertSql( IList<ColumnInfo> infos )
    {
        int len = infos.Count-1;
        string[] columns = new string[len];
        string[] values = new string[len];
        int i = 0;
        foreach( ColumnInfo info in infos ){
            if( "Id"!=info.Name ){
                columns[i] = info.Name; 
                values[i] = "@"+info.Name;
                ++i;         
            }
        }
            
        return string.Format( _InsertSql, infos[0].Table.Name, string.Join(",",columns),string.Join(",",values) );
    }
    
    private static string GenUpdateSql( IList<ColumnInfo> infos )
    {
        string[] ss = new string[infos.Count-1];
        int i = 0;
        foreach( ColumnInfo info in infos )
        {
            if( "Id"!=info.Name ){
                ss[i] = string.Concat(info.Name,"=@",info.Name);
                ++i;
            }
        }
        
        return string.Format( _UpdateSql, infos[0].Table.Name,string.Join(",",ss) );
    }
    
    private static string GenDeleteSql( IList<ColumnInfo> infos )
    {
        return string.Format( _DeleteSql,infos[0].Table.Name );
    }
    
    private static string GetSqlParameters( IList<ColumnInfo> infos )
    {
        int len = infos.Count;
        string[] declareParms = new string[len];
        string[] buildParms = new string[len];
        string[] ss = new string[len];
        
        int i = 0;
        foreach( ColumnInfo info in infos ){
            ss[i] = "PARM_"+info.Name;
            declareParms[i] = string.Format( _Parm_Name,ss[i],info.Name );
            
            string length = info.Length;
            if( !string.IsNullOrEmpty(length) )
                length = ","+length;
            buildParms[i] = string.Concat( "new SqlParameter( ",ss[i],",SqlDbType.",info.Type,length," )" );
            ++i;
        }

        return string.Concat( string.Join( "\r\n",declareParms ),"\r\n\r\n",
                              string.Format( _SqlParameters,string.Join( ",\r\n",buildParms ) )
                             );
    }
}
#endregion Data

#region Html
public class FormInfo
{
    public string Name = "";
    public IList<ElementInfo> Fields = new List<ElementInfo>();
    
    public FormInfo( XmlNode node )
    {
        Name = node.Attributes["name"].Value;
        XmlNodeList list = node.SelectNodes( "property" );
        foreach( XmlNode info in list )
            Fields.Add( new ElementInfo( this,info ) );
    }
}
public class ElementInfo
{
    public string Name = "";     // 签名
    public string Tag = "";      // 标签
    public string Type = "";     // 类型
    public string Value = "";    // 默认值

    public FormInfo Form = null;
    
    // 构造器
    public ElementInfo( FormInfo form,XmlNode node )
    {           
        this.Form = form;
        this.Name = " name='" + node.Attributes["name"].Value+"'";
        
        node = node.SelectSingleNode("html");
        if( null==node )
            return;
               
        // 必选
        this.Tag = node.Attributes["tag"].Value;
        
        // 可选
        if( null!=node.Attributes["type"] )
            this.Type = " type='" + node.Attributes["type"].Value + "'";
        if( null!=node.Attributes["value"] )
            this.Value = " value='" + node.Attributes["value"].Value + "'";
    }
}

public class GenHtml
{
    public static string HtmlTemplate( FormInfo info )
    {
        return GenForm( info.Fields );
    }
    
    private static string GenForm( IList<ElementInfo> infos )
    {
        StringBuilder sb = new StringBuilder();
        foreach( ElementInfo info in infos )
            sb.Append( string.Concat("<",info.Tag,info.Name,info.Type,info.Value,"></",info.Tag,">\r\n") );
            
        return sb.ToString();
    }
}
#endregion Html


//信息辅助器